#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>


#define PATH_NAME "."
#define PROJ_ID 1

const int SHM_SIZE = 4096;
const int MODE     = 0664;


int shmHelper(int flg)
{
    key_t key = ftok(PATH_NAME, PROJ_ID);
    if (key < 0)
    {
        perror("ftok");
        exit(1);
    }

    int shmid = shmget(key, SHM_SIZE, flg);
    if (shmid < 0)
    {
        perror("shmget");
        exit(2);
    }

    return shmid;
}

int createShm()
{
    umask(00);
    return shmHelper(IPC_CREAT | IPC_EXCL | MODE);
}

int getShm()
{
    return shmHelper(IPC_CREAT);
}

char* attachShm(int shmid)
{
    char* ptr = (char*)shmat(shmid, nullptr, 0);
    if (ptr <= (char*)0)
    {
        perror("shmat");
        exit(3);
    }
    return ptr;
}

void detachShm(char* ptr)
{
    int n = shmdt(ptr);
    if (n < 0)
    {
        perror("shmdt");
        exit(4);
    }
}

void deleteShm(int shmid)
{
    int n = shmctl(shmid, IPC_RMID, nullptr);
    if (n < 0)
    {
        perror("shmctl");
        exit(5);
    }
}


void createFifo(const char* fifo_name)
{
    umask(00);
    if (mkfifo(fifo_name, MODE) < 0)
    {
        perror("mkfifo");
        exit(6);
    }
}

int openFifo(const char* file_name, int mode)
{
    int fd = open(file_name, mode);
    if (fd < 0)
    {
        perror("open");
        exit(7);
    }
    return fd;
}

void closeFifo(int fd)
{
    if (close(fd) < 0)
    {
        perror("close");
        exit(8);
    }
}

void notify(int fd)
{
    int signal = 1;
    write(fd, &signal, sizeof(signal));
}

bool wait(int fd)
{
    int signal = 0;
    read(fd, &signal, sizeof(signal));
    return signal == 1;
}
